/*********************************************************************************/
/*                                                                               */
/*      ADC Driver                                                               */
/*                                                                               */
/*      Last updated by:  CBS                                                    */
/*      Last update date: 12/12/25                                               */
/*      Revision:         0                                                      */
/*      Copyright:        DENSO                                                  */
/*                                                                               */
/*********************************************************************************/

/*********************************************************************************/
/*  include files                                                                */
/*********************************************************************************/
#include "MPC5674F_MVx264.h"
#include "Adc.h"

/*********************************************************************************/
/*  prototypes                                                                   */
/*********************************************************************************/
void Adc_ConfigureEQADCInterrupts (void);
static void Adc_WriteEQADCRegister (Adc_EQADCRegisterType reg, Adc_EQADCRegister value);
static Adc_EQADCRegister Adc_ReadEQADCRegister (Adc_EQADCRegisterType reg);
static void  Adc_ConfigureEQADC (const Adc_ConfigType *ConfigPtr);
static void Adc_EQADCCalibrationSequence (void);
static Std_ReturnType Adc_CheckInit (const Adc_ConfigType *ConfigPtr);
static Std_ReturnType Adc_CheckDeInit(void);
static Std_ReturnType Adc_CheckSetupResultBuffer (Adc_GroupType group, Adc_ValueGroupType* dataBufferPtr);
static Std_ReturnType Adc_CheckStartGroupConversion (Adc_GroupType group);
static Std_ReturnType Adc_CheckStopGroupConversion (Adc_GroupType group);
static Std_ReturnType Adc_CheckReadGroup (Adc_GroupType group);
static Std_ReturnType Adc_CheckEnableHardwareTrigger(Adc_GroupType group);
static Std_ReturnType Adc_CheckDisableHardwareTrigger(Adc_GroupType group);
static Std_ReturnType Adc_CheckEnableGroupNotification (Adc_GroupType group);
static Std_ReturnType Adc_CheckDisableGroupNotification (Adc_GroupType group);
static Std_ReturnType Adc_CheckGetStreamLastPointer(Adc_GroupType group);
static Std_ReturnType Adc_CheckGetGroupStatus(Adc_GroupType group);
static Std_ReturnType Adc_CheckGetVersionInfo(Std_VersionInfoType* versioninfo);
void Det_ReportError(U2 a, U1 b, U1 c, U1 d);

/*********************************************************************************/
/*  defines / data types / structs / unions / macros                             */
/*********************************************************************************/
#define EQADC_FIFO0_END_OF_QUEUE_PRIORITY   (U1)(2)
#define EQADC_FIFO1_END_OF_QUEUE_PRIORITY   (U1)(2)
#define EQADC_FIFO2_END_OF_QUEUE_PRIORITY   (U1)(2)
#define EQADC_FIFO3_END_OF_QUEUE_PRIORITY   (U1)(2)
#define EQADC_FIFO4_END_OF_QUEUE_PRIORITY   (U1)(2)
#define EQADC_FIFO5_END_OF_QUEUE_PRIORITY   (U1)(2)

#define EQADC_FISR0_EOQF   (U2)(103)        /* Vector Number Of EQADC_FISR0[EOQF] */
#define EQADC_FISR1_EOQF   (U2)(108)        /* Vector Number Of EQADC_FISR1[EOQF] */
#define EQADC_FISR2_EOQF   (U2)(113)        /* Vector Number Of EQADC_FISR2[EOQF] */
#define EQADC_FISR3_EOQF   (U2)(118)        /* Vector Number Of EQADC_FISR3[EOQF] */
#define EQADC_FISR4_EOQF   (U2)(123)        /* Vector Number Of EQADC_FISR4[EOQF] */
#define EQADC_FISR5_EOQF   (U2)(128)        /* Vector Number Of EQADC_FISR5[EOQF] */

/*********************************************************************************/
/*  constants                                                                    */
/*********************************************************************************/

/* Pointer to configuration structure */
static const Adc_ConfigType *AdcConfigPtr;

/* Command queue for calibration sequence */
Adc_CommandType AdcCalibrationCommandQueue[8];

/* DMA configuration for calibration sequence */
const struct tcd_t AdcCalibrationDMACommandConfig =
{
    (U4)AdcCalibrationCommandQueue,         /* Source Address */
    0,                                      /* Source Address Modulo */
    DMA_TRANSFER_SIZE_32BITS,               /* Source Data Transfer Size */
    0,                                      /* Destination Address Modulo */
    DMA_TRANSFER_SIZE_32BITS,               /* Destination Data Transfer Size */
    sizeof(Adc_CommandType),                /* Signed Source Address Offset */
    sizeof(Adc_CommandType),                /* Inner ("Minor") Byte Transfer Count */
    0,                                      /* Last Source Address Adjustment */
    (U4)&EQADC_A.CFPR[0].R,                   /* Destination Address */
    0,                                      /* Enable Channel-to-Channel Linking on Minor Loop Completion */
    0,                                      /* Current Major Iteration Count */
    0,                                      /* Signed Destination Address Offset */
    0,                                      /* Last Destination Address Adjustment, or Scatter/Gather Address (if E_SG = 1) */
    0,                                      /* Enable Channel-to-Channel Linking on Minor Loop Complete */
    0,                                      /* Starting ("Major") Iteration Count */
    0,                                      /* Bandwidth Control */
    0,                                      /* Link Channel Number */
    0,                                      /* Channel Done */
    0,                                      /* Channel Active */
    0,                                      /* Enable Channel-to-Channel Link */
    0,                                      /* Enable Scatter/Gather Descriptor */
    0,                                      /* Disable IPD_REQ When Done */
    0,                                      /* Interrupt on CITER = (BITER >> 1) */
    0,                                      /* Interrupt on Major Loop Completion */
    0                                       /* Explicit Channel Start */
};

const struct tcd_t AdcCalibrationDMAResultConfig =
{
    (volatile U4)&EQADC_A.RFPR[0].R + 2,      /* Source Address */
    0,                                      /* Source Address Modulo */
    DMA_TRANSFER_SIZE_16BITS,               /* Source Data Transfer Size */
    0,                                      /* Destination Address Modulo */
    DMA_TRANSFER_SIZE_16BITS,               /* Destination Data Transfer Size */
    0,                                      /* Signed Source Address Offset */
    sizeof(Adc_ValueGroupType),             /* Inner ("Minor") Byte Transfer Count */
    0,                                      /* Last Source Address Adjustment */
    0,                                      /* Destination Address */
    0,                                      /* Enable Channel-to-Channel Linking on Minor Loop Completion */
    0,                                      /* Current Major Iteration Count */
    sizeof(Adc_ValueGroupType),             /* Signed Destination Address Offset */
    0,                                      /* Last Destination Address Adjustment, or Scatter/Gather Address (if E_SG = 1) */
    0,                                      /* Enable Channel-to-Channel Linking on Minor Loop Complete */
    0,                                      /* Starting ("Major") Iteration Count */
    0,                                      /* Bandwidth Control */
    0,                                      /* Link Channel Number */
    0,                                      /* Channel Done */
    0,                                      /* Channel Active*/
    0,                                      /* Enable Channel-to-Channel Link */
    0,                                      /* Enable Scatter/Gather Descriptor */
    0,                                      /* Disable IPD_REQ When Done */
    0,                                      /* Interrupt on CITER = (BITER >> 1) */
    0                                       /* Explicit Channel Start */
};

/*********************************************************************************/
/*  variables                                                                    */
/*********************************************************************************/
typedef union
{
    volatile U4 R;
    struct
    {
        volatile U4 EOQ:1;              /* End Of Queue Bit */
        volatile U4 PAUSE:1;            /* Pause Bit */
        volatile U4 REP:1;              /* Repeat/loop Start Point Indication */
        volatile U4 :2;
        volatile U4 EN:1;               /* External Buffer Bit */
        volatile U4 BN:1;               /* Buffer Number Bit */
        volatile U4 RW:1;               /* Read/Write Bit */
        volatile U4 ADC_REG:16;         /* ADC Register Field */
        volatile U4 ADC_REG_ADDR:8;     /* ADC Register Address */
    }B;
}Adc_RegisterWriteType;

typedef union
{
    volatile U4 R;
    struct
    {
        volatile U4 EOQ:1;              /* End Of Queue Bit */
        volatile U4 PAUSE:1;            /* Pause Bit */
        volatile U4 REP:1;              /* Repeat/loop Start Point Indication */
        volatile U4 :2;
        volatile U4 EN:1;               /* External Buffer Bit */
        volatile U4 BN:1;               /* Buffer Number Bit */
        volatile U4 RW:1;               /* Read/Write Bit */
        volatile U4 MESSAGE_TAG:4;      /* MESSAGE_TAG Field */
        volatile U4 :12;
        volatile U4 ADC_REG_ADDR:8;     /* ADC Register Address */
   }B;
}Adc_RegisterReadType;

typedef enum
{
    ADC_UNINIT,
    ADC_INIT
}Adc_StateType;

typedef enum
{
    ADC_EQADC_QUEUE_0,
    ADC_EQADC_QUEUE_1,
    ADC_EQADC_QUEUE_2,
    ADC_EQADC_QUEUE_3,
    ADC_EQADC_QUEUE_4,
    ADC_EQADC_QUEUE_5,
    ADC_EQADC_NBR_OF_QUEUES
}Adc_EQADCQueueType;

typedef enum
{
    EQADC_CFIFO_STATUS_IDLE = 0,
    EQADC_CFIFO_STATUS_WAITINGFOR_TRIGGER = 0x2,
    EQADC_CFIFO_STATUS_TRIGGERED = 0x3
}Adc_EQADCQueueStatusType;

#if (ADC_VERSION_INFO_API == STD_ON)
static Std_VersionInfoType ADC_VersionInfo =
{
    ADC_VENDOR_ID, 
    MODULE_ID_ADC,
    ADC_INSTANCE_ID,
    ADC_SW_MAJOR_VERSION,
    ADC_SW_MINOR_VERSION,
    ADC_SW_PATCH_VERSION,
    ADC_AR_MAJOR_VERSION,
    ADC_AR_MINOR_VERSION,
    ADC_AR_PATCH_VERSION 
};
#endif

static Adc_StateType adcState = ADC_UNINIT;

/*********************************************************************************/
/*  API Functions                                                                */
/*********************************************************************************/

/***************************************************************************************************/
/*  Service name    :   Adc_Init                                                                   */
/*  Sync/Async      :   Synchronous                                                                */
/*  Reentrancy      :   Non Reentrant                                                              */
/*  Parameters (in) :   Pointer to configuration set in Variant PB(Variant PC requires a NULL_PTR) */
/*  Return value    :   None                                                                       */
/*  Discription     :   Initializes the ADC hardware units and driver                              */
/***************************************************************************************************/
void Adc_Init (const Adc_ConfigType *ConfigPtr)
{
    Adc_ChannelType channel;
    Adc_ChannelType channelId;
    Adc_GroupType group;
    Adc_CommandType *commandQueue;
    Adc_CommandType command;

    if (E_OK == Adc_CheckInit(ConfigPtr))
    {
        AdcConfigPtr = ConfigPtr;

        /* Start configuring the eQADC queues */
        for ( group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++ )
        {
            /* Loop through all channels and make the command queue */
            for (channel = ADC_CH0; channel < ConfigPtr->groupConfigPtr[group].numberOfChannels; channel++)
            {
                /* Get physical channel */
                channelId = ConfigPtr->groupConfigPtr[group].channelList[channel];
                commandQueue = ConfigPtr->groupConfigPtr[group].commandBuffer;
                /* Begin with empty command */
                command.R = 0;
                /* Physical channel number */
                command.B.CHANNEL_NUMBER = channelId;
                /* Sample time */
                command.B.LST = ConfigPtr->channelConfigPtr [channel].adcChannelConvTime;
                /* Calibration feature */
                command.B.CAL = ConfigPtr->channelConfigPtr [channel].adcChannelCalibrationEnable;
                /* Result buffer FIFO. The number of groups must not be greater than the number of queues */
                command.B.MESSAGE_TAG = group;
                /* Write command to command queue */
                commandQueue [channel].R = command.R;
                /* Last channel in group. Write EOQ and configure eQADC FIFO */
                if (channel == (ConfigPtr->groupConfigPtr[group].numberOfChannels - 1))
                {
                    commandQueue [channel].B.EOQ = 1;
                }
            }
        }

        /* Enable ADC */
        Adc_ConfigureEQADC(ConfigPtr);

        /* Perform calibration of the ADC */
        Adc_EQADCCalibrationSequence();

        /* Configure DMA channels */
        for ( group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++ )
        {
            /* ADC307 */
            ConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
            ConfigPtr->groupConfigPtr[group].status->notifictionEnable = 0;

            Dma_ConfigureChannel ((struct tcd_t *)ConfigPtr->groupConfigPtr [group].groupDMAResults, ConfigPtr->groupConfigPtr [group].dmaResultChannel);
            Dma_ConfigureChannel ((struct tcd_t *)ConfigPtr->groupConfigPtr [group].groupDMACommands, ConfigPtr->groupConfigPtr [group].dmaCommandChannel);
        }

        /* Start DMA channels */
        for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)
        {
            /* Invalidate queues */
            EQADC_A.CFCR[group].B.CFINV = 1;
        }

        Adc_ConfigureEQADCInterrupts ();  /* Configure Interrupts */

        adcState = ADC_INIT;
    }

}

/*******************************************************************************************************/
/*  Service name    :   Adc_DeInit                                                                     */
/*  Sync/Async      :   Synchronous                                                                    */
/*  Reentrancy      :   Non Reentrant                                                                  */
/*  Parameters      :   none                                                                           */
/*  Return value    :   none                                                                           */
/*  Discription     :   Returns all ADC HW Units to a state comparable to their power on reset state   */
/*******************************************************************************************************/
#if (ADC_DEINIT_API == STD_ON)
void Adc_DeInit (void)
{
    Adc_EQADCQueueType queue;
    Adc_GroupType group;
    U1 queueStopped;
  
    if (E_OK == Adc_CheckDeInit())
    {
        /* Stop all queues */
        for (queue = ADC_EQADC_QUEUE_0; queue < ADC_EQADC_NBR_OF_QUEUES; queue++)
        {
            /* Disable queue */
            EQADC_A.CFCR[queue].B.MODE = 0;

            /* Wait for queue to enter idle state */
            queueStopped = FALSE;
            while (!queueStopped)
            {
                switch (queue)
                {
                    case ADC_EQADC_QUEUE_0:
                        if(EQADC_A.CFSR.B.CFS0 == EQADC_CFIFO_STATUS_IDLE)
                        {
                            queueStopped = TRUE;
                        }
                        break;
                    case ADC_EQADC_QUEUE_1:
                        if(EQADC_A.CFSR.B.CFS1 == EQADC_CFIFO_STATUS_IDLE)
                        {
                            queueStopped = TRUE;
                        }
                        break;
                    case ADC_EQADC_QUEUE_2:
                        if(EQADC_A.CFSR.B.CFS2 == EQADC_CFIFO_STATUS_IDLE)
                        {
                            queueStopped = TRUE;
                        }
                        break;
                    case ADC_EQADC_QUEUE_3:
                        if(EQADC_A.CFSR.B.CFS3 == EQADC_CFIFO_STATUS_IDLE)
                        {
                            queueStopped = TRUE;
                        }
                        break;
                    case ADC_EQADC_QUEUE_4:
                        if(EQADC_A.CFSR.B.CFS4 == EQADC_CFIFO_STATUS_IDLE)
                        {
                            queueStopped = TRUE;
                        }
                        break;
                    case ADC_EQADC_QUEUE_5:
                        if(EQADC_A.CFSR.B.CFS5 == EQADC_CFIFO_STATUS_IDLE)
                        {
                            queueStopped = TRUE;
                        }
                        break;
                    default :
                        queueStopped = TRUE;
                        break;
                }
            }

        /* Disable eDMA requests for commands and results */
        EQADC_A.IDCR[queue].B.CFFS = 0;
        EQADC_A.IDCR[queue].B.RFDS = 0;

        /* Disable FIFO fill requests */
        EQADC_A.IDCR[queue].B.CFFE = 0;
        EQADC_A.IDCR[queue].B.RFDE = 0;

        /* Disable interrupts */
        EQADC_A.IDCR[queue].B.RFOIE = 0;
        EQADC_A.IDCR[queue].B.CFUIE = 0;
        EQADC_A.IDCR[queue].B.TORIE = 0;
        EQADC_A.IDCR[queue].B.EOQIE = 0;
    }

    /* Stop all DMA channels connected to EQADC */
    for ( group = ADC_GROUP0; group < AdcConfigPtr->nbrOfGroups; group++ )
    {
        /* Set group status to idle */
        AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
    }

    /* Disable EQADC */
    Adc_WriteEQADCRegister(ADC0_CR, 0);

    /* Clean internal status */
    AdcConfigPtr = (Adc_ConfigType *)0;
    adcState = ADC_UNINIT;
  }
}
#endif

/************************************************************************************************************************/
/*  Service name    :    Adc_SetupResultBuffer                                                                          */
/*  Sync/Async.     :    Synchronous                                                                                    */
/*  Reentrancy      :    Re-entrant                                                                                     */
/*  Parameters (in) :    Group               Numeric ID of requested ADC channel group.                                 */
/*                       DataBufferPtr       pointer to result data buffer                                              */
/*  Return value    :    Std_ReturnType      E_OK: result buffer pointer initialized correctly                          */
/*                                           E_NOT_OK: operation failed or development error occured                    */
/*  Discription     :    Initializes ADC driver with the group specific result buffer start address where the           */
/*                       conversion results will be stored. The application has to ensure that the application buffer,  */
/*                       where DataBufferPtr points to, can hold all the conversion results of the specified group.     */
/*                       The initialization with Adc_SetupResultBuffer is required after reset, before a group          */
/*                       conversion can be started.                                                                     */
/*************************************************************************************************************************/
Std_ReturnType Adc_SetupResultBuffer(Adc_GroupType group, Adc_ValueGroupType* dataBufferPtr)
{
    Std_ReturnType returnValue;

    /* Check for development errors */
    if (E_OK == Adc_CheckSetupResultBuffer (group, dataBufferPtr))
    {
        Dma_StopChannel(AdcConfigPtr->groupConfigPtr[group].dmaCommandChannel);
        Dma_StopChannel(AdcConfigPtr->groupConfigPtr[group].dmaResultChannel);
        AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr = dataBufferPtr;
        Dma_ConfigureDestinationAddress((U4)dataBufferPtr, AdcConfigPtr->groupConfigPtr[group].dmaResultChannel);
        Dma_StartChannel(AdcConfigPtr->groupConfigPtr[group].dmaResultChannel);
        Dma_StartChannel(AdcConfigPtr->groupConfigPtr[group].dmaCommandChannel);
        returnValue = E_OK;
    }
    else
    {
        /* An error have been raised from Adc_CheckSetupResultBuffer() */
        returnValue = E_NOT_OK;
    }
    return(returnValue);
}

/***************************************************************************************************/
/*  Service name    :    Adc_StartGroupConversion                                                  */
/*  Sync/Async      :    ASynchronous                                                              */
/*  Reentrancy      :    Re-entrant                                                                */
/*  Parameters (in) :    Group         Numeric ID of requested ADC Channel group.                  */
/*  Return value    :    none                                                                      */
/*  Description     :    Starts the conversion of all channels of the requested ADC Channel group. */
/***************************************************************************************************/
#if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)  /* ADC259 */
void Adc_StartGroupConversion (Adc_GroupType group)
{
    /* Run development error check */
    if (E_OK == Adc_CheckStartGroupConversion (group))
    {
        Dma_StartChannel(AdcConfigPtr->groupConfigPtr[group].dmaResultChannel);
        Dma_StartChannel(AdcConfigPtr->groupConfigPtr[group].dmaCommandChannel);
        /* Set conversion mode */
        EQADC_A.CFCR[group].B.MODE = AdcConfigPtr->groupConfigPtr[group].conversionMode;
        /* Set single scan enable bit if this group is one shot. */
        if (AdcConfigPtr->groupConfigPtr[group].conversionMode == ADC_CONV_MODE_ONESHOT)
        {
            EQADC_A.CFCR[group].B.SSE = 1;

            /* Set group state to BUSY */
            AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;
        }
    }
}
#endif

/***************************************************************************************************/
/*  Service name    :    Adc_StopGroupConversion                                                   */
/*  Sync/Async.     :    Synchronous                                                               */
/*  Reentrancy      :    Re-entrant                                                                */
/*  Parameters (in) :    Group         Numeric ID of requested ADC Channel group.                  */
/*  Return value    :    none                                                                      */
/*  Description     :    Stops the conversion of the requested ADC Channel group.                  */
/***************************************************************************************************/
#if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)  /* ADC260 */
void Adc_StopGroupConversion(Adc_GroupType group)
{
    /*Run development error check */
    if (E_OK == Adc_CheckStopGroupConversion(group))
    {
        Dma_StopChannel(AdcConfigPtr->groupConfigPtr[group].dmaCommandChannel);
        Dma_StopChannel(AdcConfigPtr->groupConfigPtr[group].dmaResultChannel);

        EQADC_A.CFCR[group].B.MODE = ADC_CONV_MODE_DISABLED;

        /* Set group state to IDLE */
        AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
    }
}
#endif

/********************************************************************************************************************/
/*  Service name    :    Adc_ReadGroup                                                                              */
/*  Sync/Async.     :    Synchronous                                                                                */
/*  Reentrancy      :    Re-entrant                                                                                 */
/*  Parameters (in) :    Group             Numeric ID of requested ADC Channel group.                               */
/*                       DataBufferPtr     ADC results of all channels of the selected group are                    */
/*                                         stored in the data buffer addressed with the pointer.                    */
/*  Return value    :    Std_ReturnType    E_OK: results are available and written to the data buffer               */
/*                                         E_NOT_OK: no results are available or development error occured          */
/*  Description    :     Reads the group conversion result of the last completed conversion round of the            */
/*                       requested group and stores the channel values starting at the DataBufferPtr                */
/*                       address. The group channel values are stored in ascending channel number order             */
/*                       (in contrast to the storage layout of the result buffer if streaming access is configured).*/
/********************************************************************************************************************/
#if (ADC_READ_GROUP_API == STD_ON)
Std_ReturnType Adc_ReadGroup(Adc_GroupType group, Adc_ValueGroupType *dataBufferPtr)
{
    Std_ReturnType returnValue;
    Adc_ChannelType channel;
    U1 i;

    if (E_OK == Adc_CheckReadGroup (group))
    {
        if ((ADC_CONV_MODE_CONTINOUS == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&
         ((ADC_STREAM_COMPLETED    == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||
          (ADC_COMPLETED           == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))
        {
            /* ADC329, ADC331 */
            AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;
            returnValue = E_OK;
        }
        else if ((ADC_CONV_MODE_ONESHOT == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&
             (ADC_STREAM_COMPLETED  == AdcConfigPtr->groupConfigPtr[group].status->groupStatus))
        {
            /* ADC330 */
            AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;

            returnValue = E_OK;
        }
        else
        {
            /* Keep status */
            returnValue = E_OK;
        }

        i = 0;
    
        if (E_OK == returnValue)
        {
            /* Copy the result to application buffer */
            for (channel = ADC_CH0; channel < AdcConfigPtr->groupConfigPtr[group].numberOfChannels; channel += AdcConfigPtr->groupConfigPtr[group].streamNumSamples)
            {
                dataBufferPtr[i] = AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr[channel];
                i++;
            } 
        }
    }
    else
    {
        /* An error have been raised from Adc_CheckReadGroup() */
        returnValue = E_NOT_OK;
    }

    return (returnValue);
}
#endif

/***************************************************************************************************/
/*  Service name    :    Adc_EnableHardwareTrigger                                                 */
/*  Sync/Async      :    Synchronous                                                               */
/*  Reentrancy      :    Re-entrant                                                                */
/*  Parameters (in) :    Group         Numeric ID of requested ADC Channel group.                  */
/*  Return value    :    none                                                                      */
/*  Description     :    Enables the hardware trigger for the requested ADC Channel group.         */
/***************************************************************************************************/
#if (ADC_HW_TRIGGER_API == STD_ON)  /* ADC265 */
void Adc_EnableHardwareTrigger(Adc_GroupType group)
{
    if (E_OK == Adc_CheckEnableHardwareTrigger(group))
    {    
        Dma_StartChannel(AdcConfigPtr->groupConfigPtr[group].dmaResultChannel);
        Dma_StartChannel(AdcConfigPtr->groupConfigPtr[group].dmaCommandChannel);

        /* Set conversion mode */
        EQADC_A.CFCR[group].B.MODE = AdcConfigPtr->groupConfigPtr[group].hwTriggerSignal;

        /* Set group state to BUSY */
        AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;    
    }
}
#endif

/***************************************************************************************************/
/*  Service name    :    Adc_DisableHardwareTrigger                                                */
/*  Sync/Async      :    Synchronous                                                               */
/*  Reentrancy      :    Re-entrant                                                                */
/*  Parameters (in) :    Group         Numeric ID of requested ADC Channel group.                  */
/*  Return value    :    none                                                                      */
/*  Description     :    Disables the hardware trigger for the requested ADC Channel group.        */
/***************************************************************************************************/
#if (ADC_HW_TRIGGER_API == STD_ON)  /* ADC266 */
void Adc_DisableHardwareTrigger(Adc_GroupType group)
{
    if (E_OK == Adc_CheckDisableHardwareTrigger(group))
    {
        Dma_StopChannel(AdcConfigPtr->groupConfigPtr[group].dmaCommandChannel);
        Dma_StopChannel(AdcConfigPtr->groupConfigPtr[group].dmaResultChannel);

        /* Set conversion mode */
        EQADC_A.CFCR[group].B.MODE = ADC_CONV_MODE_DISABLED;

        /* Set group state to IDLE */
        AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
    }
}
#endif

/***************************************************************************************************/
/*  Service name    :    Adc_EnableGroupNotification                                               */
/*  Sync/Async      :    Synchronous                                                               */
/*  Reentrancy      :    Re-entrant                                                                */
/*  Parameters (in) :    Group         Numeric ID of requested ADC Channel group.                  */
/*  Return value    :    none                                                                      */
/*  Description     :    Enables the notification mechanism for the requested ADC Channel group.   */
/***************************************************************************************************/
#if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)  /* ADC100 */
void Adc_EnableGroupNotification(Adc_GroupType group)
{
    /* Check for development errors */
    if (E_OK == Adc_CheckEnableGroupNotification(group))
    {
        AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable = 1;
    }
}
#endif

/***************************************************************************************************/
/*  Service name    :    Adc_DisableGroupNotification                                              */
/*  Sync/Async      :    Synchronous                                                               */
/*  Reentrancy      :    Re-entrant                                                                */
/*  Parameters (in) :    Group         Numeric ID of requested ADC Channel group.                  */
/*  Return value    :    none                                                                      */
/*  Description     :    Disables the notification mechanism for the requested ADC Channel group.  */
/***************************************************************************************************/
#if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)  /* ADC101 */
void Adc_DisableGroupNotification(Adc_GroupType group)
{
    /* Check for development errors */
    if (E_OK == Adc_CheckDisableGroupNotification (group))
    {
        AdcConfigPtr->groupConfigPtr[group].status->notifictionEnable = 0;
    }
}
#endif

/***************************************************************************************************/
/*  Service name    :    Adc_GetGroupStatus                                                        */
/*  Sync/Async      :    Synchronous                                                               */
/*  Reentrancy      :    Re-entrant                                                                */
/*  Parameters (in) :    Group              Numeric ID of requested ADC Channel group.             */
/*  Return value    :    Adc_StatusType     Conversion status for the requested group.             */
/*  Description     :    Returns the conversion status of the requested ADC Channel group.         */
/***************************************************************************************************/
Adc_StatusType Adc_GetGroupStatus(Adc_GroupType group)
{
    Adc_StatusType returnValue;

    /* Check for development errors. */
    if(E_OK == Adc_CheckGetGroupStatus(group))
    {
        returnValue = AdcConfigPtr->groupConfigPtr[group].status->groupStatus;
    }
    else
    {
        returnValue = ADC_IDLE;  /* ADC225 ADC301 */
    }
    return(returnValue);
}

/*********************************************************************************************************************/
/*  Service name    :    Adc_GetStreamLastPointer                                                                    */
/*  Sync/Async.     :    Synchronous                                                                                 */
/*  Reentrancy      :    Re-entrant                                                                                  */
/*  Parameters (in) :    Group               Numeric ID of requested ADC Channel group.                              */
/*  Parameters (out):    PtrToSamplePtr      Pointer to result buffer pointer.                                       */
/*  Return value    :    Adc_StreamNumSampleType     Number of valid samples per channel.                            */
/*  Description     :    Returns the number of valid samples per channel, stored in the result buffer.               */
/*                       Reads a pointer, pointing to a position in the group result buffer. With the pointer        */
/*                       position, the results of all group channels of the last completed conversion round          */
/*                       can be accessed.With the pointer and the return value, all valid group conversion results   */
/*                       can be accessed (the user has to take the layout of the result buffer into account).        */
/*********************************************************************************************************************/
Adc_StreamNumSampleType Adc_GetStreamLastPointer(Adc_GroupType group,Adc_ValueGroupType** ptrToSamplePtr)
{
    Adc_StreamNumSampleType returnValue;

    if (E_OK == Adc_CheckGetStreamLastPointer(group))
    {
        if ((ADC_CONV_MODE_CONTINOUS == AdcConfigPtr->groupConfigPtr[group].conversionMode) &&
           ((ADC_STREAM_COMPLETED    == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||
            (ADC_COMPLETED           == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))
        {
            AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_BUSY;
        }
        else
        {
            AdcConfigPtr->groupConfigPtr[group].status->groupStatus = ADC_IDLE;
        }

        *ptrToSamplePtr = &(AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr[AdcConfigPtr->groupConfigPtr[group].streamNumSamples - 1]);
        returnValue = AdcConfigPtr->groupConfigPtr[group].streamNumSamples;
    }
    else
    {
        /* An error have been raised from Adc_CheckGetStreamLastPointer() */
        *ptrToSamplePtr = 0;
        returnValue = 0;
    }

    return (returnValue);
}

/************************************************************************************************************/
/*  Service name    :    Adc_GetVersionInfo                                                                 */
/*  Sync/Async      :    Synchronous                                                                        */
/*  Reentrancy      :    Re-entrant                                                                         */
/*  Parameters (in) :    versioninfo     Pointer to where to store the version information of this module.  */
/*  Return value    :    none                                                                               */
/*  Description     :    Returns the version information of this module.                                    */
/************************************************************************************************************/
#if (ADC_VERSION_INFO_API == STD_ON)  /* ADC237 */
void Adc_GetVersionInfo(Std_VersionInfoType* versioninfo)
{
    if(E_OK == Adc_CheckGetVersionInfo(versioninfo))
    {
        versioninfo->vendorID = ADC_VersionInfo.vendorID;
        versioninfo->moduleID = ADC_VersionInfo.moduleID;
        versioninfo->instanceID = ADC_VersionInfo.instanceID;

        versioninfo->sw_major_version = ADC_VersionInfo.sw_major_version;
        versioninfo->sw_minor_version = ADC_VersionInfo.sw_minor_version;
        versioninfo->sw_patch_version = ADC_VersionInfo.sw_patch_version;

        versioninfo->ar_major_version = ADC_VersionInfo.ar_major_version;
        versioninfo->ar_minor_version = ADC_VersionInfo.ar_minor_version;
        versioninfo->ar_patch_version = ADC_VersionInfo.ar_patch_version;
    }
}
#endif

/************************************************************************/
/*    Local Functions                                                   */
/************************************************************************/
void Adc_Group0ConversionComplete(void)
{
    /* ISR for FIFO 0 end of queue. Clear interrupt flag */
    EQADC_A.FISR[ADC_EQADC_QUEUE_0].B.EOQF = 1;

    /* Sample completed */
    AdcConfigPtr->groupConfigPtr[ADC_GROUP0].status->groupStatus = ADC_STREAM_COMPLETED;

    /* Call notification if enabled */
#if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
    if (AdcConfigPtr->groupConfigPtr[ADC_GROUP0].status->notifictionEnable && AdcConfigPtr->groupConfigPtr[ADC_GROUP0].groupCallback != 0)
    {
        AdcConfigPtr->groupConfigPtr[ADC_GROUP0].groupCallback();
    }
#endif
}

void Adc_Group1ConversionComplete(void)
{
    /* ISR for FIFO 1 end of queue. Clear interrupt flag */
    EQADC_A.FISR[ADC_EQADC_QUEUE_1].B.EOQF = 1;

    /* Sample completed */
    AdcConfigPtr->groupConfigPtr[ADC_GROUP1].status->groupStatus = ADC_STREAM_COMPLETED;

    /* Call notification if enabled */
#if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
    if (AdcConfigPtr->groupConfigPtr[ADC_GROUP1].status->notifictionEnable && AdcConfigPtr->groupConfigPtr[ADC_GROUP1].groupCallback != 0)
    {
        AdcConfigPtr->groupConfigPtr[ADC_GROUP1].groupCallback();
    }
#endif
}

void Adc_Group2ConversionComplete(void)
{
    /* ISR for FIFO 2 end of queue. Clear interrupt flag */
    EQADC_A.FISR[ADC_EQADC_QUEUE_2].B.EOQF = 1;

    /* Sample completed */
    AdcConfigPtr->groupConfigPtr[ADC_GROUP2].status->groupStatus = ADC_STREAM_COMPLETED;

    /* Call notification if enabled */
#if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
    if (AdcConfigPtr->groupConfigPtr[ADC_GROUP2].status->notifictionEnable && AdcConfigPtr->groupConfigPtr[ADC_GROUP2].groupCallback != 0)
    {
        AdcConfigPtr->groupConfigPtr[ADC_GROUP2].groupCallback();
    }
#endif
}

void Adc_Group3ConversionComplete(void)
{
  /* ISR for FIFO 3 end of queue. Clear interrupt flag */
  EQADC_A.FISR[ADC_EQADC_QUEUE_3].B.EOQF = 1;

  /* Sample completed. */
  AdcConfigPtr->groupConfigPtr[ADC_GROUP3].status->groupStatus = ADC_STREAM_COMPLETED;

  /* Call notification if enabled. */
#if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
  if (AdcConfigPtr->groupConfigPtr[ADC_GROUP3].status->notifictionEnable && AdcConfigPtr->groupConfigPtr[ADC_GROUP3].groupCallback != 0)
  {
      AdcConfigPtr->groupConfigPtr[ADC_GROUP3].groupCallback();
  }
#endif
}

void Adc_Group4ConversionComplete(void)
{
    /* ISR for FIFO 4 end of queue. Clear interrupt flag */
    EQADC_A.FISR[ADC_EQADC_QUEUE_4].B.EOQF = 1;

    /* Sample completed */
    AdcConfigPtr->groupConfigPtr[ADC_GROUP4].status->groupStatus = ADC_STREAM_COMPLETED;

    /* Call notification if enabled */
#if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
    if (AdcConfigPtr->groupConfigPtr[ADC_GROUP4].status->notifictionEnable && AdcConfigPtr->groupConfigPtr[ADC_GROUP4].groupCallback != 0)
    {
        AdcConfigPtr->groupConfigPtr[ADC_GROUP4].groupCallback();
    }
#endif
}

void Adc_Group5ConversionComplete(void)
{
    /* ISR for FIFO 5 end of queue. Clear interrupt flag */
    EQADC_A.FISR[ADC_EQADC_QUEUE_5].B.EOQF = 1;

    /* Sample completed */
    AdcConfigPtr->groupConfigPtr[ADC_GROUP5].status->groupStatus = ADC_STREAM_COMPLETED;

    /* Call notification if enabled */
#if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)
    if (AdcConfigPtr->groupConfigPtr[ADC_GROUP5].status->notifictionEnable && AdcConfigPtr->groupConfigPtr[ADC_GROUP5].groupCallback != 0)
    {
        AdcConfigPtr->groupConfigPtr[ADC_GROUP5].groupCallback();
    }
#endif
}

void Adc_ConfigureEQADCInterrupts(void)
{
    Adc_GroupType group;

    INTC_InitINTCInterrupts();

    INTC_InstallINTCInterruptHandler(Adc_Group0ConversionComplete,EQADC_FISR0_EOQF,EQADC_FIFO0_END_OF_QUEUE_PRIORITY);
    INTC_InstallINTCInterruptHandler(Adc_Group1ConversionComplete,EQADC_FISR1_EOQF,EQADC_FIFO1_END_OF_QUEUE_PRIORITY);
    INTC_InstallINTCInterruptHandler(Adc_Group2ConversionComplete,EQADC_FISR2_EOQF,EQADC_FIFO2_END_OF_QUEUE_PRIORITY);
    INTC_InstallINTCInterruptHandler(Adc_Group3ConversionComplete,EQADC_FISR3_EOQF,EQADC_FIFO3_END_OF_QUEUE_PRIORITY);
    INTC_InstallINTCInterruptHandler(Adc_Group4ConversionComplete,EQADC_FISR4_EOQF,EQADC_FIFO4_END_OF_QUEUE_PRIORITY);
    INTC_InstallINTCInterruptHandler(Adc_Group5ConversionComplete,EQADC_FISR5_EOQF,EQADC_FIFO5_END_OF_QUEUE_PRIORITY);
  
    for (group = ADC_GROUP0; group < AdcConfigPtr->nbrOfGroups; group++)
    {
        /* Enable end of queue, queue overflow/underflow interrupts. Clear corresponding flags */
        EQADC_A.FISR[group].B.RFOF = 1;
        EQADC_A.IDCR[group].B.RFOIE = 1;

        EQADC_A.FISR[group].B.CFUF = 1;
        EQADC_A.IDCR[group].B.CFUIE = 1;

        EQADC_A.FISR[group].B.TORF = 1;
        EQADC_A.IDCR[group].B.TORIE = 1;

        EQADC_A.FISR[group].B.EOQF = 1;
        EQADC_A.IDCR[group].B.EOQIE = 1;
    }
}

#define WAIT_FOR_QUEUE_TO_FINISH(q) \
  while (EQADC_A.FISR[q].B.SSS)             \
  {                                       \
    ;                                     \
  }                                       \
                                          \
  while (!EQADC_A.FISR[q].B.EOQF)           \
  {                                       \
    ;                                     \
  }

static void Adc_WriteEQADCRegister (Adc_EQADCRegisterType reg, Adc_EQADCRegister value)
{
    Adc_RegisterWriteType writeReg;
    U4 temp, oldMode;

    writeReg.R = 0;

    /* Write command */
    writeReg.B.RW = 0;
    writeReg.B.EOQ = 1;
    writeReg.B.ADC_REG = value;
    writeReg.B.ADC_REG_ADDR = reg;

    /* Invalidate queue */
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.CFINV = 1;

    /* Write command through FIFO */
    EQADC_A.CFPR[ADC_EQADC_QUEUE_0].R = writeReg.R;

    /* Enable FIFO */
    oldMode = EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.MODE;
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.MODE = ADC_CONV_MODE_ONESHOT;
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.SSE = 1;

    /* Wait for command to be executed */
    WAIT_FOR_QUEUE_TO_FINISH(ADC_EQADC_QUEUE_0);

    /* Flush result buffer */
    temp = EQADC_A.RFPR[ADC_EQADC_QUEUE_0].R;
    
    EQADC_A.FISR[ADC_EQADC_QUEUE_0].B.EOQF = 1;
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.MODE = oldMode;
}

static Adc_EQADCRegister Adc_ReadEQADCRegister(Adc_EQADCRegisterType reg)
{
    Adc_RegisterReadType readReg;
    Adc_EQADCRegister result;
    U4 oldMode, dmaRequestEnable;

    readReg.R = 0;

    /* Read command */
    readReg.B.RW = 1;
    readReg.B.EOQ = 1;
    readReg.B.ADC_REG_ADDR = reg;
    readReg.B.MESSAGE_TAG = ADC_EQADC_QUEUE_0;

    /* Make sure that DMA requests for command fill and result drain is disabled */
    if (EQADC_A.IDCR[ADC_EQADC_QUEUE_0].B.RFDE || EQADC_A.IDCR[ADC_EQADC_QUEUE_0].B.CFFE)
    {
        EQADC_A.IDCR[ADC_EQADC_QUEUE_0].B.CFFE = 0;
        EQADC_A.IDCR[ADC_EQADC_QUEUE_0].B.RFDE = 0;

        dmaRequestEnable = TRUE;
    }
    else
    {
        dmaRequestEnable = FALSE;
    }

    /* Invalidate queue */
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.CFINV = 1;

    /* Write command through FIFO */
    EQADC_A.CFPR[ADC_EQADC_QUEUE_0].R = readReg.R;

    /* Enable FIFO */
    oldMode = EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.MODE;
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.MODE = ADC_CONV_MODE_ONESHOT;
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.SSE = 1;

    /* Wait for command to be executed */
    WAIT_FOR_QUEUE_TO_FINISH(ADC_EQADC_QUEUE_0);

    /* Read result buffer */
    result = (U2)EQADC_A.RFPR[ADC_EQADC_QUEUE_0].B.RFPOP;
    EQADC_A.FISR[ADC_EQADC_QUEUE_0].B.EOQF = 1;

    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.MODE = oldMode;

    if (dmaRequestEnable)
    {
      EQADC_A.IDCR[ADC_EQADC_QUEUE_0].B.CFFE = 1;
      EQADC_A.IDCR[ADC_EQADC_QUEUE_0].B.RFDE = 1;
    }

    return (result);
}

static void  Adc_ConfigureEQADC(const Adc_ConfigType *ConfigPtr)
{
    Adc_GroupType group;

    enum
    {
        ADC_ENABLE = 0x8000
    };
    /* Enable ADC0 */
    Adc_WriteEQADCRegister(ADC0_CR, (ADC_ENABLE | (U2)ConfigPtr->hwConfigPtr->adcPrescale));

    /* Disable time stamp timer */
    Adc_WriteEQADCRegister (ADC0_TSCR, 0);

    for (group = ADC_GROUP0; group < ConfigPtr->nbrOfGroups; group++)
    {
        /* Enable eDMA requests for commands and results */
        EQADC_A.IDCR[group].B.CFFS = 1;
        EQADC_A.IDCR[group].B.RFDS = 1;

        /* Invalidate FIFO */
        EQADC_A.CFCR[group].B.CFINV = 1;

        /* Enable FIFO fill requests */
        EQADC_A.IDCR[group].B.CFFE = 1;
        EQADC_A.IDCR[group].B.RFDE = 1;
    }
}

static void Adc_EQADCCalibrationSequence(void)
{
    Adc_ValueGroupType calibrationResult[sizeof(AdcCalibrationCommandQueue)/sizeof(AdcCalibrationCommandQueue[0])];
    S4 point25Average, point75Average;
    U2 i;
    double resultOfTempGCC, resultOfTempOCC;
    Adc_EQADCRegister tempGCC, tempOCC;
    
    const double IDEAL_RES25 = 4096.0;    /* 25% reference voltage */
    const double IDEAL_RES75 = 12288.0;   /* 75% reference voltage */

    for(i = 0;i < 4;i++)
    {
        AdcCalibrationCommandQueue[i].B.EOQ = 0;
        AdcCalibrationCommandQueue[i].B.PAUSE = 0;
        AdcCalibrationCommandQueue[i].B.REP = 0;
        AdcCalibrationCommandQueue[i].B.EB = 0;
        AdcCalibrationCommandQueue[i].B.BN = 0;
        AdcCalibrationCommandQueue[i].B.CAL = 0;
        AdcCalibrationCommandQueue[i].B.MESSAGE_TAG = 0;
        AdcCalibrationCommandQueue[i].B.LST = ADC_CONVERSION_TIME_128_CLOCKS;
        AdcCalibrationCommandQueue[i].B.TSR = 0;
        AdcCalibrationCommandQueue[i].B.FMT = 0;
        AdcCalibrationCommandQueue[i].B.CHANNEL_NUMBER = 44;
    }

    for(i = 4;i < 7;i++)
    {
        AdcCalibrationCommandQueue[i].B.EOQ = 0;
        AdcCalibrationCommandQueue[i].B.PAUSE = 0;
        AdcCalibrationCommandQueue[i].B.REP = 0;
        AdcCalibrationCommandQueue[i].B.EB = 0;
        AdcCalibrationCommandQueue[i].B.BN = 0;
        AdcCalibrationCommandQueue[i].B.CAL = 0;
        AdcCalibrationCommandQueue[i].B.MESSAGE_TAG = 0;
        AdcCalibrationCommandQueue[i].B.LST = ADC_CONVERSION_TIME_128_CLOCKS;
        AdcCalibrationCommandQueue[i].B.TSR = 0;
        AdcCalibrationCommandQueue[i].B.FMT = 0;
        AdcCalibrationCommandQueue[i].B.CHANNEL_NUMBER = 43;
    }

    AdcCalibrationCommandQueue[7].B.EOQ = 1;
    AdcCalibrationCommandQueue[7].B.PAUSE = 0;
    AdcCalibrationCommandQueue[7].B.REP = 0;
    AdcCalibrationCommandQueue[7].B.EB = 0;
    AdcCalibrationCommandQueue[7].B.BN = 0;
    AdcCalibrationCommandQueue[7].B.CAL = 0;
    AdcCalibrationCommandQueue[7].B.MESSAGE_TAG = 0;
    AdcCalibrationCommandQueue[7].B.LST = ADC_CONVERSION_TIME_128_CLOCKS;
    AdcCalibrationCommandQueue[7].B.TSR = 0;
    AdcCalibrationCommandQueue[7].B.FMT = 0;
    AdcCalibrationCommandQueue[7].B.CHANNEL_NUMBER = 43;

    /* Use group 0 DMA channel for calibration */
    Dma_ConfigureChannel ((struct tcd_t *)&AdcCalibrationDMACommandConfig,DMA_ADC_GROUP0_COMMAND_CHANNEL);
    Dma_ConfigureChannelTranferSize (sizeof(AdcCalibrationCommandQueue)/sizeof(AdcCalibrationCommandQueue[0]),DMA_ADC_GROUP0_COMMAND_CHANNEL);
    Dma_ConfigureChannelSourceCorr ((S4)(-sizeof(AdcCalibrationCommandQueue)), DMA_ADC_GROUP0_COMMAND_CHANNEL);
    Dma_ConfigureChannel ((struct tcd_t *)&AdcCalibrationDMAResultConfig, DMA_ADC_GROUP0_RESULT_CHANNEL);
    Dma_ConfigureChannelTranferSize (sizeof(calibrationResult)/sizeof(calibrationResult[0]),DMA_ADC_GROUP0_RESULT_CHANNEL);
    Dma_ConfigureChannelDestinationCorr ((S4)(-sizeof(calibrationResult)), DMA_ADC_GROUP0_RESULT_CHANNEL);
    Dma_ConfigureDestinationAddress ((U4)calibrationResult, DMA_ADC_GROUP0_RESULT_CHANNEL);

    /* Invalidate queues */
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.CFINV = 1;

    Dma_StartChannel (DMA_ADC_GROUP0_COMMAND_CHANNEL);
    Dma_StartChannel (DMA_ADC_GROUP0_RESULT_CHANNEL);

    /* Start conversion */
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.MODE = ADC_CONV_MODE_ONESHOT;
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.SSE = 1;

    /* Wait for conversion to complete */
    while(!Dma_ChannelDone(DMA_ADC_GROUP0_RESULT_CHANNEL))
    {
        ;
    }

    /* Stop DMA channels and write calibration data to ADC engine */
    EQADC_A.CFCR[ADC_EQADC_QUEUE_0].B.MODE = ADC_CONV_MODE_DISABLED;
    Dma_StopChannel(DMA_ADC_GROUP0_COMMAND_CHANNEL);
    Dma_StopChannel(DMA_ADC_GROUP0_RESULT_CHANNEL);

    /* Calculate conversion factors and write to ADC */
    point25Average = 0;
    point75Average = 0;
    
    for ( i = 0; i < sizeof(calibrationResult)/sizeof(calibrationResult[0] / 2); i++ )
    {
        point25Average += calibrationResult[i];
        point75Average += calibrationResult[i + sizeof(calibrationResult)/sizeof(calibrationResult[0]) / 2];
    }
  
    /* Calculate average and correction slope and offset */
    point25Average /= (sizeof(calibrationResult)/sizeof(calibrationResult[0]) / 2);
    point75Average /= (sizeof(calibrationResult)/sizeof(calibrationResult[0]) / 2);

    /* Calculate average and correction slope and offset */
    resultOfTempGCC = (IDEAL_RES75 - IDEAL_RES25) / (point75Average - point25Average);
    resultOfTempOCC = IDEAL_RES75 - (resultOfTempGCC * point75Average) - 2;

    tempGCC = 0;
    tempOCC = 0;

    tempGCC = (U2)(resultOfTempGCC * 16384);  /* 16384 = 2 ^ 14 */

    if(resultOfTempOCC < 0)
    {
        tempOCC = (U2)((-1) * resultOfTempOCC);
        tempOCC = (U2)((U2)(~tempOCC) + 1);
        tempOCC = tempOCC | (1 << 13);
    }
    else
    {
        tempOCC = (U2)resultOfTempOCC;
    }

    /* GCC field is only 15 bits */
    tempGCC = tempGCC & ~(1 << 15);

    /* OCC field is only 14 bits */
    tempOCC = tempOCC & ~(3 << 14);

    /* Write calibration data to ADC engine */
    Adc_WriteEQADCRegister(ADC0_GCCR, tempGCC);
    Adc_WriteEQADCRegister(ADC0_OCCR, tempOCC);
}

static Std_ReturnType Adc_CheckInit(const Adc_ConfigType *ConfigPtr)
{
    Std_ReturnType returnValue;

#if ( ADC_DEV_ERROR_DETECT == STD_ON )
    if (!(ADC_UNINIT == adcState))
    {
        /* ADC107 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_INIT_ID, ADC_E_ALREADY_INITIALIZED );
        returnValue = E_NOT_OK;
    }
    else if (ConfigPtr == (Adc_ConfigType*)0)
    {
        /* Wrong config */
        /* ADC343 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_INIT_ID, ADC_E_PARAM_CONFIG );
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return(returnValue);
}

#if (ADC_DEINIT_API == STD_ON)
static Std_ReturnType Adc_CheckDeInit(void)
{
    Std_ReturnType returnValue;
#if( ADC_DEV_ERROR_DETECT == STD_ON )
    Adc_GroupType group;
    U1 nbrOfGroupStatusError;
  
    nbrOfGroupStatusError = 0;
  
    for (group = ADC_GROUP0; group < AdcConfigPtr->nbrOfGroups; group++)
    {
        if (!((AdcConfigPtr->groupConfigPtr[group].status->groupStatus == ADC_IDLE)
           || (AdcConfigPtr->groupConfigPtr[group].status->groupStatus == ADC_STREAM_COMPLETED)))
        {
            nbrOfGroupStatusError++;
        }
    }

    if (ADC_UNINIT == adcState)
    {
        /* ADC154 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_DEINIT_ID, ADC_E_UNINIT);
        returnValue = E_NOT_OK;
    }
    else if (nbrOfGroupStatusError >0)
    {
        /* ADC112 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_DEINIT_ID, ADC_E_BUSY);
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return (returnValue);
}
#endif

static Std_ReturnType Adc_CheckSetupResultBuffer(Adc_GroupType group, Adc_ValueGroupType* dataBufferPtr)
{
    Std_ReturnType returnValue;

#if ( ADC_DEV_ERROR_DETECT == STD_ON )
    if (ADC_UNINIT == adcState)
    {
        /* Driver not initialised */
        /* ADC434 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_SETUPRESULTBUFFER_ID,ADC_E_UNINIT );
        returnValue = E_NOT_OK;
    }
    else if (!(group < AdcConfigPtr->nbrOfGroups))
    {
        /* ADC423 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_SETUPRESULTBUFFER_ID,ADC_E_PARAM_GROUP );
        returnValue = E_NOT_OK;
    }
    else if (!(ADC_IDLE == AdcConfigPtr->groupConfigPtr[group].status->groupStatus))
    {
        /* ADC433 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_SETUPRESULTBUFFER_ID,ADC_E_BUSY);
        returnValue = E_NOT_OK;
    }
    else if(0 == dataBufferPtr)
    {
        /* ADC457 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_SETUPRESULTBUFFER_ID,ADC_E_PARAM_POINTER);
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return (returnValue);
}

#if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)  /* ADC259 */
static Std_ReturnType Adc_CheckStartGroupConversion(Adc_GroupType group)
{
    Std_ReturnType returnValue;
#if ( ADC_DEV_ERROR_DETECT == STD_ON )
    if (!(ADC_INIT == adcState))
    {
        /* ADC not initialised */
        /* ADC294 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_STARTGROUPCONVERSION_ID, ADC_E_UNINIT );
        returnValue = E_NOT_OK;
    }
    else if (0 == AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr)
    {
        /*Result buffer pointer not initialised */
        /* ADC424 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_STARTGROUPCONVERSION_ID, ADC_E_BUFFER_UNINIT );
        returnValue = E_NOT_OK;
    }
    else if (!((group >= 0) && (group < AdcConfigPtr->nbrOfGroups)))
    {
        /* Wrong group ID */
        /* ADC125 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_STARTGROUPCONVERSION_ID, ADC_E_PARAM_GROUP );
        returnValue = E_NOT_OK;
    }
    else if (!(ADC_TRIGG_SRC_SW == AdcConfigPtr->groupConfigPtr[group].triggerSrc))
    {
        /* Wrong trig source */
        /* ADC133 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_STARTGROUPCONVERSION_ID, ADC_E_WRONG_TRIGG_SRC);
        returnValue = E_NOT_OK;
    }
    else if (!((ADC_IDLE == AdcConfigPtr->groupConfigPtr[group].status->groupStatus) ||
             (ADC_STREAM_COMPLETED == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)))
    {
        /* Group status not OK */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_STARTGROUPCONVERSION_ID, ADC_E_BUSY );
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
        returnValue = E_OK;
#endif
    return(returnValue);
}
#endif

#if (ADC_ENABLE_START_STOP_GROUP_API == STD_ON)  /* ADC260 */
static Std_ReturnType Adc_CheckStopGroupConversion(Adc_GroupType group)
{
    Std_ReturnType returnValue;
#if ( ADC_DEV_ERROR_DETECT == STD_ON )
    if (!(ADC_INIT == adcState))
    {
        /* ADC not initialised */
        /* ADC295 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_STOPGROUPCONVERSION_ID, ADC_E_UNINIT );
        returnValue = E_NOT_OK;
    }
    else if (!((group >= 0) && (group < AdcConfigPtr->nbrOfGroups)))
    {
        /* Wrong group ID */
        /* ADC126 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_STOPGROUPCONVERSION_ID, ADC_E_PARAM_GROUP );
        returnValue = E_NOT_OK;
    }
    else if (!(ADC_TRIGG_SRC_SW == AdcConfigPtr->groupConfigPtr[group].triggerSrc))
    {
        /* Wrong trig source */
        /* ADC164 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_STOPGROUPCONVERSION_ID, ADC_E_WRONG_TRIGG_SRC);
        returnValue = E_NOT_OK;
    }
    else if (ADC_IDLE == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)
    {
        /* Group status not OK */
        /* ADC241 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_STOPGROUPCONVERSION_ID, ADC_E_IDLE);
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return(returnValue);
}
#endif

#if (ADC_READ_GROUP_API == STD_ON)
static Std_ReturnType Adc_CheckReadGroup(Adc_GroupType group)
{
    Std_ReturnType returnValue;
#if ( ADC_DEV_ERROR_DETECT == STD_ON )
    if (ADC_UNINIT == adcState)
    {
        /* ADC296 */
        returnValue = E_NOT_OK;
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_READGROUP_ID ,ADC_E_UNINIT );
    }
    else if ((group < 0) || (group >= AdcConfigPtr->nbrOfGroups))
    {
        /* ADC152 */
        returnValue = E_NOT_OK;
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_READGROUP_ID ,ADC_E_PARAM_GROUP );
    }
    else if (ADC_IDLE == AdcConfigPtr->groupConfigPtr[group].status->groupStatus)
    {
        /* ADC388 */
        returnValue = E_NOT_OK;
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_READGROUP_ID ,ADC_E_IDLE );
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return(returnValue);
}
#endif

#if (ADC_HW_TRIGGER_API == STD_ON)  /* ADC265 */
static Std_ReturnType Adc_CheckEnableHardwareTrigger(Adc_GroupType group)
{
    Std_ReturnType returnValue;
#if( ADC_DEV_ERROR_DETECT == STD_ON )
    if (ADC_UNINIT == adcState)
    {
        /* Driver not initialised */
        /* ADC297 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_ENABLEHARDWARETRIGGER_ID,ADC_E_UNINIT );
        returnValue = E_NOT_OK;
    }
    else if (group > AdcConfigPtr->nbrOfGroups)
    {
        /* ADC128 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_ENABLEHARDWARETRIGGER_ID,ADC_E_PARAM_GROUP );
        returnValue = E_NOT_OK;
    }
    else if (!(ADC_TRIGG_SRC_HW == AdcConfigPtr->groupConfigPtr[group].triggerSrc))
    {
        /* ADC136 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_ENABLEHARDWARETRIGGER_ID, ADC_E_WRONG_TRIGG_SRC);
        returnValue = E_NOT_OK;
    }
    else if (ADC_CONV_MODE_CONTINOUS == AdcConfigPtr->groupConfigPtr[group].conversionMode)
    {
        /* ADC281 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_ENABLEHARDWARETRIGGER_ID, ADC_E_WRONG_CONV_MODE);
        returnValue = E_NOT_OK;
    }
    else if(0 == AdcConfigPtr->groupConfigPtr[group].status->resultBufferPtr)
    {
        /* Result buffer pointer not initialised */
        /* ADC425 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_ENABLEHARDWARETRIGGER_ID, ADC_E_BUFFER_UNINIT );
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return (returnValue);
}
#endif

#if (ADC_HW_TRIGGER_API == STD_ON)  /* ADC266 */
static Std_ReturnType Adc_CheckDisableHardwareTrigger(Adc_GroupType group)
{
    Std_ReturnType returnValue;
#if ( ADC_DEV_ERROR_DETECT == STD_ON )
    if (ADC_UNINIT == adcState)
    {
        /* Driver not initialised */
        /* ADC298 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_DISABLEHARDWARETRIGGER_ID,ADC_E_UNINIT );
        returnValue = E_NOT_OK;
    }
    else if (group > AdcConfigPtr->nbrOfGroups)
    {
        /* ADC129 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_DISABLEHARDWARETRIGGER_ID,ADC_E_PARAM_GROUP );
        returnValue = E_NOT_OK;
    }
    else if (!(ADC_TRIGG_SRC_HW == AdcConfigPtr->groupConfigPtr[group].triggerSrc))
    {
        /* ADC137 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_DISABLEHARDWARETRIGGER_ID, ADC_E_WRONG_TRIGG_SRC);
        returnValue = E_NOT_OK;
    }
    else if (ADC_CONV_MODE_CONTINOUS == AdcConfigPtr->groupConfigPtr[group].conversionMode)
    {
        /* ADC282 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_DISABLEHARDWARETRIGGER_ID, ADC_E_WRONG_CONV_MODE);
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return(returnValue);
}
#endif

#if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)  /* ADC100 */
static Std_ReturnType Adc_CheckEnableGroupNotification(Adc_GroupType group)
{
    Std_ReturnType returnValue;
#if ( ADC_DEV_ERROR_DETECT == STD_ON )
    if (ADC_UNINIT == adcState)
    {
        /* Driver not initialised */
        /*ADC299*/
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_ENABLEGROUPNOTIFICATION_ID,ADC_E_UNINIT );
        returnValue = E_NOT_OK;
    }
    else if (group > AdcConfigPtr->nbrOfGroups)
    {
        /* ADC130 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_ENABLEGROUPNOTIFICATION_ID,ADC_E_PARAM_GROUP );
        returnValue = E_NOT_OK;
    }
    else if (AdcConfigPtr->groupConfigPtr[group].groupCallback == 0)
    {
        /* ADC165 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_ENABLEGROUPNOTIFICATION_ID,ADC_E_NOTIF_CAPABILITY );
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return(returnValue);
}
#endif

#if (ADC_GRP_NOTIF_CAPABILITY == STD_ON)  /* ADC101 */
static Std_ReturnType Adc_CheckDisableGroupNotification(Adc_GroupType group)
{
    Std_ReturnType returnValue;
#if ( ADC_DEV_ERROR_DETECT == STD_ON )
    if (ADC_UNINIT == adcState)
    {
        /* Driver not initialised */
        /* ADC299 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_DISABLEGROUPNOTIFICATION_ID,ADC_E_UNINIT );
        returnValue = E_NOT_OK;
    }
    else if (group > AdcConfigPtr->nbrOfGroups)
    {
        /* ADC130 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_DISABLEGROUPNOTIFICATION_ID,ADC_E_PARAM_GROUP );
        returnValue = E_NOT_OK;
    }
    else if (AdcConfigPtr->groupConfigPtr[group].groupCallback == 0)
    {
        /* ADC166 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_DISABLEGROUPNOTIFICATION_ID,ADC_E_NOTIF_CAPABILITY );
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return(returnValue);
}
#endif

static Std_ReturnType Adc_CheckGetStreamLastPointer(Adc_GroupType group)
{
    Std_ReturnType returnValue;
#if(ADC_DEV_ERROR_DETECT == STD_ON)
    if (ADC_UNINIT == adcState)
    {
        /* Driver not initialised */
        /* ADC302 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_GETSTREAMLASTPOINTER_ID,ADC_E_UNINIT );
        returnValue = E_NOT_OK;
    }
    else if (group > AdcConfigPtr->nbrOfGroups)
    {
        /* ADC218 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_GETSTREAMLASTPOINTER_ID,ADC_E_PARAM_GROUP );
        returnValue = E_NOT_OK;
    }
    else if (AdcConfigPtr->groupConfigPtr[group].status->groupStatus == ADC_IDLE)
    {
        /* ADC215 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_GETSTREAMLASTPOINTER_ID,ADC_E_IDLE);
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return(returnValue);
}

static Std_ReturnType Adc_CheckGetGroupStatus(Adc_GroupType group)
{
    Std_ReturnType returnValue;
#if ( ADC_DEV_ERROR_DETECT == STD_ON )
    if (ADC_UNINIT == adcState)
    {
        /* Driver not initialised */
        /* ADC301 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_GETGROUPSTATUS_ID,ADC_E_UNINIT );
        returnValue = E_NOT_OK;
    }
    else if (group > AdcConfigPtr->nbrOfGroups)
    {
        /* ADC225 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_GETGROUPSTATUS_ID,ADC_E_PARAM_GROUP );
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return(returnValue);
}

#if (ADC_VERSION_INFO_API == STD_ON)  /* ADC237 */
static Std_ReturnType Adc_CheckGetVersionInfo(Std_VersionInfoType* versioninfo)
{
    Std_ReturnType returnValue;
#if( ADC_DEV_ERROR_DETECT == STD_ON )
    if( 0 == versioninfo)
    {
        /* ADC458 */
        Det_ReportError(MODULE_ID_ADC,ADC_INSTANCE_ID,ADC_GETVERSIONINFO_ID,ADC_E_PARAM_POINTER );
        returnValue = E_NOT_OK;
    }
    else
    {
        returnValue = E_OK;
    }
#else
    returnValue = E_OK;
#endif
    return(returnValue);
}
#endif

void Det_ReportError(U2 a, U1 b, U1 c, U1 d)
{
    
}

/**** End Of File ****************************************************************/
